package plp.funcoo.expressions;

import plp.funcoo.environment.compilation.CompilationEnvironment;
import plp.funcoo.environment.compilation.Environment;
import plp.funcoo.environment.execution.ExecutionEnvironment;
import plp.funcoo.exceptions.ClassAlreadyDeclared;
import plp.funcoo.exceptions.ClassNotDeclared;
import plp.funcoo.exceptions.MethodAlreadDeclared;
import plp.funcoo.exceptions.MethodNotDeclared;
import plp.funcoo.exceptions.ParameterNumberIncorrect;
import plp.funcoo.exceptions.ParameterTypeIncorrect;
import plp.funcoo.exceptions.VarAlreadyDeclared;
import plp.funcoo.exceptions.VarNotDeclared;
import plp.funcoo.util.Type;



/** 
 * Uma expressao &eacute; a unidade basica na Linguagem de Expressoes.
 */
public interface Expression {

	/**
	 * Avalia a expressao  retornando o ambiente modificado.
	 * @throws VarNotDeclared TODO
	 * @throws MethodNotDeclared TODO
	 * @throws VarAlreadyDeclared TODO
	 * @throws MethodAlreadDeclared TODO
	 */
	ExecutionEnvironment evaluate(ExecutionEnvironment envi) throws VarNotDeclared, MethodNotDeclared, VarAlreadyDeclared, MethodAlreadDeclared;

	/**
	 * Realiza a verificacao de tipos desta expressao.
	 *
	 * @return <code>true</code> se os tipos da expressao sao validos;
	 *          <code>false</code> caso contrario.
	 */
	boolean typeCheck(CompilationEnvironment envi) 	throws VarAlreadyDeclared, VarNotDeclared,
    ClassAlreadyDeclared,ClassNotDeclared,MethodAlreadDeclared,MethodNotDeclared,ParameterTypeIncorrect,ParameterNumberIncorrect;

	/**
	 * Retorna os tipos possiveis desta expressao.
	 *
	 * @return os tipos possiveis desta expressao.
	 */
	Type getType(Environment envi)throws VarNotDeclared, ClassNotDeclared;
	
	Expression makeCopy();


}
